package dao.xml.dom;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import model.DrehPlan;
import model.Drehort;
import model.Drehtag;
import model.Equipment;
import model.Spezialisation;
import model.Szene;
import model.Teammitglied;
import model.ZeitVonBis;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class DOMDrehPlanDAO {

	private final DocumentBuilder builder;
	private Document document;
	private DrehPlan drehplan;

	public DOMDrehPlanDAO() throws ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(false);
		factory.setValidating(false);
		factory.setXIncludeAware(false);
		factory.setIgnoringElementContentWhitespace(true);
		builder = factory.newDocumentBuilder();

	}

	public DrehPlan getDrehPlan(InputStream input) throws SAXException, IOException, ParseException {
		drehplan = new DrehPlan();
		document = builder.parse(input);
		Element documentElement = document.getDocumentElement();
		if (documentElement.hasChildNodes()) {
			Node node = documentElement.getFirstChild();
			while (node != null) {
				if (node.getNodeType() == Node.ELEMENT_NODE && "drehorte".equals(node.getNodeName())) {
					drehplan.setDrehorte(createDrehorteFromNode(node));
				}
				if (node.getNodeType() == Node.ELEMENT_NODE && "mitglieder".equals(node.getNodeName())) {
					drehplan.setMitglieder(createMitgliederFromNode(node));
				}
				if (node.getNodeType() == Node.ELEMENT_NODE && "equipmentliste".equals(node.getNodeName())) {
					drehplan.setEquipment(createEquipmentFromNode(node));
				}
				if (node.getNodeType() == Node.ELEMENT_NODE && "szenen".equals(node.getNodeName())) {
					drehplan.setSzenen(createSzeneFromNode(node));
				}
				if (node.getNodeType() == Node.ELEMENT_NODE && "drehtage".equals(node.getNodeName())) {
					drehplan.setDrehtage(createDrehtageFromNode(node));
				}
				node = node.getNextSibling();
			}

		}

		return drehplan;

	}

	private List<Drehtag> createDrehtageFromNode(Node drehtageNode) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
		List<Drehtag> drehtage = new LinkedList<Drehtag>();
		if (drehtageNode.hasChildNodes() && drehtageNode.getFirstChild().getNextSibling().hasChildNodes()) {
			Node drehtagNode = drehtageNode.getFirstChild().getNextSibling();
			while (drehtagNode != null) {
				if (!drehtagNode.getNodeName().trim().equalsIgnoreCase("#text")) {
					NamedNodeMap attributes = drehtagNode.getAttributes();
					String ersterDrehtermin = attributes.getNamedItem("drehtermin").getNodeValue();
					Drehtag drehtag = new Drehtag(sdf.parse(ersterDrehtermin));
					String ersatzTermin = attributes.getNamedItem("ersatztermin").getNodeValue();
					drehtag.setErsatzTermin(sdf.parse(ersatzTermin));
					String szene = attributes.getNamedItem("szene").getNodeValue();
					for(Szene s : drehplan.getSzenen()) {
						if(s.getId() == Long.parseLong(szene))
							drehtag.setSzene(s);
					}
					String drehort = attributes.getNamedItem("drehort").getNodeValue();
					for(Drehort o : drehplan.getDrehorte()) {
						if(o.getId() == Long.parseLong(drehort))
							drehtag.setDrehort(o);
					}
					String aufbauzeitvon = attributes.getNamedItem("aufbauzeitvon").getNodeValue();
					String aufbauzeitbis = attributes.getNamedItem("aufbauzeitbis").getNodeValue();
					String drehzeitvon = attributes.getNamedItem("drehzeitvon").getNodeValue();
					String drehzeitbis = attributes.getNamedItem("drehzeitbis").getNodeValue();
					sdf = new SimpleDateFormat("HH:mm dd.MM.yyyy");

					drehtag.setAufbauZeitVonBis(new ZeitVonBis(sdf.parse(aufbauzeitvon), sdf.parse(aufbauzeitbis)));
					drehtag.setDrehZeitVonBis(new ZeitVonBis(sdf.parse(drehzeitvon), sdf.parse(drehzeitbis)));

					Node drehtagChildNode = drehtagNode.getFirstChild();
					while (drehtagChildNode != null) {
						if (drehtagChildNode.hasChildNodes() && "einteilungen".equals(drehtagChildNode.getNodeName())) {
							Node einteilungNode = drehtagChildNode.getFirstChild().getNextSibling();
							while (einteilungNode != null) {
								if (!einteilungNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = einteilungNode.getAttributes();
									String rolle = attributes.getNamedItem("name").getNodeValue();
									String id = attributes.getNamedItem("id").getNodeValue();
									drehtag.addEinteilung(rolle, Long.parseLong(id));
								}
								einteilungNode = einteilungNode.getNextSibling();
							}
						}
						if (drehtagChildNode.hasChildNodes() && "bestelltesequipment".equals(drehtagChildNode.getNodeName())) {
							Node bestelltesEquipmentNode = drehtagChildNode.getFirstChild().getNextSibling();
							while (bestelltesEquipmentNode != null) {
								if (!bestelltesEquipmentNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = bestelltesEquipmentNode.getAttributes();
									String id = attributes.getNamedItem("id").getNodeValue();
									Long l = Long.parseLong(id);
									for(Equipment e : drehplan.getEquipment()) {
										if(e.getId() == l)
											drehtag.addEquipment(e);
									}
								}

								bestelltesEquipmentNode = bestelltesEquipmentNode.getNextSibling();
							}

						}

						drehtagChildNode = drehtagChildNode.getNextSibling();
					}

					drehtage.add(drehtag);
				}

				//
				//

				drehtagNode = drehtagNode.getNextSibling();
			}

		}
		return drehtage;
	}

	private List<Szene> createSzeneFromNode(Node szenenNode) {
		List<Szene> szenen = new LinkedList<Szene>();
		if (szenenNode.hasChildNodes() && szenenNode.getFirstChild().getNextSibling().hasChildNodes()) {
			Node szeneNode = szenenNode.getFirstChild().getNextSibling();
			while (szeneNode != null) {
				if (!szeneNode.getNodeName().trim().equalsIgnoreCase("#text")) {

					NamedNodeMap attributes = szeneNode.getAttributes();
					String szenennummer = attributes.getNamedItem("id").getNodeValue();
					String wetterabhaengig = attributes.getNamedItem("wetter").getNodeValue();
					Szene szene = new Szene(Integer.parseInt(szenennummer), wetterabhaengig.equalsIgnoreCase("true"));
					String name = attributes.getNamedItem("name").getNodeValue();
					szene.setName(name);
					Node szeneChildNode = szeneNode.getFirstChild();
					while (szeneChildNode != null) {
						if (szeneChildNode.hasChildNodes() && "schauspielrollen".equals(szeneChildNode.getNodeName())) {
							Node schauspielNode = szeneChildNode.getFirstChild().getNextSibling();
							while (schauspielNode != null) {
								if (!schauspielNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = schauspielNode.getAttributes();
									String rolle = attributes.getNamedItem("name").getNodeValue();
									szene.addSchauspielRolle(rolle);

								}
								schauspielNode = schauspielNode.getNextSibling();
							}
						}
						if (szeneChildNode.hasChildNodes() && "sonstpersonal".equals(szeneChildNode.getNodeName())) {
							Node personalNode = szeneChildNode.getFirstChild().getNextSibling();
							while (personalNode != null) {
								if (!personalNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = personalNode.getAttributes();
									String personal = attributes.getNamedItem("name").getNodeValue();
									szene.addSonstigesPersonal(personal);

								}
								personalNode = personalNode.getNextSibling();
							}
						}
						if (szeneChildNode.hasChildNodes() && "benoetigtesequip".equals(szeneChildNode.getNodeName())) {
							Node equipNode = szeneChildNode.getFirstChild().getNextSibling();
							while (equipNode != null) {
								if (!equipNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = equipNode.getAttributes();
									String benequip = attributes.getNamedItem("name").getNodeValue();
									szene.addBenoetigtesEquip(benequip);

								}
								equipNode = equipNode.getNextSibling();
							}
						}
						szeneChildNode = szeneChildNode.getNextSibling();

					}
					szenen.add(szene);
				}
				szeneNode = szeneNode.getNextSibling();
			}
		}
		return szenen;
	}

	private List<Equipment> createEquipmentFromNode(Node equipmentNode) throws ParseException {
		List<Equipment> equipmentlist = new LinkedList<Equipment>();
		if (equipmentNode.hasChildNodes() && equipmentNode.getFirstChild().getNextSibling().hasChildNodes()) {
			Node eNode = equipmentNode.getFirstChild().getNextSibling();
			while (eNode != null) {
				if (!eNode.getNodeName().trim().equalsIgnoreCase("#text")) {

					NamedNodeMap attributes = eNode.getAttributes();
					String name = attributes.getNamedItem("name").getNodeValue();
					Equipment e = new Equipment(name);
					String id = attributes.getNamedItem("id").getNodeValue();
					e.setId(Long.parseLong(id));
					String beschreibung = attributes.getNamedItem("beschreibung").getNodeValue();
					e.setBeschreibung(beschreibung);
					String accessoir = attributes.getNamedItem("accessoir").getNodeValue();
					e.setAccessoir("true".equalsIgnoreCase(accessoir));
					String aufbaudauer = attributes.getNamedItem("aufbaudauer").getNodeValue();
					e.setAufbauDauer(Integer.parseInt(aufbaudauer));
					String gemietet = attributes.getNamedItem("gemietet").getNodeValue();
					e.setGemietet("true".equalsIgnoreCase(gemietet));
					String immervorhanden = attributes.getNamedItem("immervorhanden").getNodeValue();
					e.setImmervorhanden("true".equalsIgnoreCase(immervorhanden));
					String vorhanden = attributes.getNamedItem("vorhanden").getNodeValue();
					e.setVorhanden("true".equalsIgnoreCase(vorhanden));
					String strom = attributes.getNamedItem("strom").getNodeValue();
					e.setStrom("true".equalsIgnoreCase(strom));
					String zeitvon = attributes.getNamedItem("zeitvon").getNodeValue();
					String zeitbis = attributes.getNamedItem("zeitbis").getNodeValue();

					SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
					e.setVorhandenZeit(new ZeitVonBis(sdf.parse(zeitvon), sdf.parse(zeitbis)));

					equipmentlist.add(e);

				}

				eNode = eNode.getNextSibling();
			}
		}
		return equipmentlist;
	}

	private List<Teammitglied> createMitgliederFromNode(Node mitgliederNode) throws ParseException {
		List<Teammitglied> teammitglieder = new LinkedList<Teammitglied>();
		if (mitgliederNode.hasChildNodes() && mitgliederNode.getFirstChild().getNextSibling().hasChildNodes()) {
			Node mitgliedNode = mitgliederNode.getFirstChild().getNextSibling();
			while (mitgliedNode != null) {
				if (!mitgliedNode.getNodeName().trim().equalsIgnoreCase("#text")) {
					SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
					NamedNodeMap attributes = mitgliedNode.getAttributes();

					String vName = attributes.getNamedItem("vname").getNodeValue();
					String nName = attributes.getNamedItem("nname").getNodeValue();

					Teammitglied mitglied = new Teammitglied(vName, nName);

					String id = attributes.getNamedItem("id").getNodeValue();
					mitglied.setId(Long.parseLong(id));
					String handynr = attributes.getNamedItem("handynr").getNodeValue();
					mitglied.setHandynummer(handynr);
					String geburtstag = attributes.getNamedItem("geburtstag").getNodeValue();
					mitglied.setGeburtstag(sdf.parse(geburtstag));
					String erlaubnis = attributes.getNamedItem("erlaubnis").getNodeValue();
					mitglied.setErlaubnis("true".equalsIgnoreCase(erlaubnis));
					String email = attributes.getNamedItem("email").getNodeValue();
					mitglied.seteMailAdresse(email);

					Node mitgliedChildNode = mitgliedNode.getFirstChild();
					while (mitgliedChildNode != null) {
						if (mitgliedChildNode.hasChildNodes() && "arbeitszeiten".equals(mitgliedChildNode.getNodeName())) {
							Node arbeitszeitenNode = mitgliedChildNode.getFirstChild().getNextSibling();
							while (arbeitszeitenNode != null) {
								if (!arbeitszeitenNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = arbeitszeitenNode.getAttributes();
									String von = attributes.getNamedItem("von").getNodeValue();
									String bis = attributes.getNamedItem("bis").getNodeValue();

									ZeitVonBis arbeitszeit = new ZeitVonBis(sdf.parse(von), sdf.parse(bis));
									mitglied.addArbeitszeit(arbeitszeit);

								}
								arbeitszeitenNode = arbeitszeitenNode.getNextSibling();
							}
						}
						if (mitgliedChildNode.hasChildNodes() && "rollen".equals(mitgliedChildNode.getNodeName())) {
							Node rollenNode = mitgliedChildNode.getFirstChild().getNextSibling();
							while (rollenNode != null) {
								if (!rollenNode.getNodeName().trim().equalsIgnoreCase("#text")) {
									attributes = rollenNode.getAttributes();
									String name = attributes.getNamedItem("name").getNodeValue();
									for (Spezialisation spez : Spezialisation.values()) {
										if (name.equals(spez.getTag()))
											mitglied.addRolle(spez);
									}
								}
								rollenNode = rollenNode.getNextSibling();
							}
						}
						mitgliedChildNode = mitgliedChildNode.getNextSibling();
					}
					teammitglieder.add(mitglied);
				}
				mitgliedNode = mitgliedNode.getNextSibling();
			}
		}
		return teammitglieder;
	}

	private List<Drehort> createDrehorteFromNode(Node drehorteNode) throws ParseException {
		List<Drehort> drehorte = new LinkedList<Drehort>();
		if (drehorteNode.hasChildNodes() && drehorteNode.getFirstChild().getNextSibling().hasChildNodes()) {
			Node drehortNode = drehorteNode.getFirstChild().getNextSibling();
			while (drehortNode != null) {
				if (!drehortNode.getNodeName().trim().equalsIgnoreCase("#text")) {
					SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
					NamedNodeMap attributes = drehortNode.getAttributes();

					String drehortname = attributes.getNamedItem("name").getNodeValue();
					String locationScout = attributes.getNamedItem("scout").getNodeValue();

					Drehort drehort = new Drehort(drehortname, locationScout);

					String id = attributes.getNamedItem("id").getNodeValue();
					drehort.setId(Long.parseLong(id));
					String moeglicheSzene = attributes.getNamedItem("moeglicheSzene").getNodeValue();
					drehort.setMoeglicheSzene(moeglicheSzene);
					String strasse = attributes.getNamedItem("strasse").getNodeValue();
					drehort.setStrasse(strasse);
					String beschreibung = attributes.getNamedItem("beschreibung").getNodeValue();
					drehort.setBeschreibung(beschreibung);
					String plz = attributes.getNamedItem("plz").getNodeValue();
					drehort.setPlz(Integer.parseInt(plz));
					String ort = attributes.getNamedItem("ort").getNodeValue();
					drehort.setOrt(ort);
					String genehmigung = attributes.getNamedItem("genehmigung").getNodeValue();
					drehort.setGenehmigung("true".equalsIgnoreCase(genehmigung));

					String von = attributes.getNamedItem("von").getNodeValue();
					String bis = attributes.getNamedItem("bis").getNodeValue();
					ZeitVonBis genehmigungsZeitspanne = new ZeitVonBis(sdf.parse(von), sdf.parse(bis));
					drehort.setGenehmigungsZeitspanne(genehmigungsZeitspanne);

					drehorte.add(drehort);
				}
				drehortNode = drehortNode.getNextSibling();
			}
		}
		return drehorte;
	}

}
